#include "GLFWView.h"
#include <GLFW/glfw3.h>

USE_JLIB_NS


GLFWView::GLFWView () {
  glfwSetErrorCallback(&onError);
  glfwInit();
}

void GLFWView::pollEvents () {
  glfwPollEvents();
}

void GLFWView::swapBuffers () {
  debug_assert(_window);
  glfwSwapBuffers(_window);
}

bool GLFWView::createWindow (Listener* listener, const WindowConfig& config) {
  debug_assert(!_window);
  glfwWindowHint(GLFW_RESIZABLE, config.flags & WindowConfig::Resizable ? GL_TRUE : GL_FALSE);
  glfwWindowHint(GLFW_DOUBLEBUFFER, config.flags & WindowConfig::DoubleBuffer ? GL_TRUE : GL_FALSE);
  glfwWindowHint(GLFW_RED_BITS, config.color);
  glfwWindowHint(GLFW_GREEN_BITS, config.color);
  glfwWindowHint(GLFW_BLUE_BITS, config.color);
  glfwWindowHint(GLFW_DEPTH_BITS, config.depth);
  glfwWindowHint(GLFW_STENCIL_BITS, config.stencil);
  glfwWindowHint(GLFW_SAMPLES, config.samples);
  auto window = glfwCreateWindow(config.width, config.height, config.name.c_str(), nullptr, nullptr);
  if (!window)
    return false;
  glfwSetWindowPosCallback(window, &onWindowPos);
  glfwSetWindowSizeCallback(window, &onWindowSize);
  glfwSetWindowCloseCallback(window, &onWindowClose);
  glfwSetWindowFocusCallback(window, &onWindowFocus);
  glfwSetWindowIconifyCallback(window, &onWindowIconify);
  glfwSetFramebufferSizeCallback(window, &onFramebufferSize);
  glfwSetMouseButtonCallback(window, &onMouseButton);
  glfwSetCursorPosCallback(window, &onCursorPos);
  glfwSetCursorEnterCallback(window, &onCursorEnter);
  glfwSetScrollCallback(window, &onScroll);
  glfwSetKeyCallback(window, &onKey);
  glfwSetCharCallback(window, &onChar);
  _window = window;
  _listener = listener;
  return true;
}

void GLFWView::destroyWindow () {
  debug_assert(_window);
  glfwDestroyWindow(_window);
  _window = nullptr;
}

void GLFWView::onError (int error, const char* info) {
  abort_assert(false, "GLFW Error(%d): %s", error, info);
}

void GLFWView::onWindowPos (GLFWwindow*, int x, int y) {
}

void GLFWView::onWindowSize (GLFWwindow*, int w, int h) {
}

void GLFWView::onWindowClose (GLFWwindow*) {
  auto thiz = instance();
  thiz->_listener->onClose();
}

void GLFWView::onWindowFocus (GLFWwindow*, int focused) {
  auto thiz = instance();
  if (focused == GL_TRUE)
    thiz->_listener->onResume();
  else
    thiz->_listener->onPause();
}

void GLFWView::onWindowIconify (GLFWwindow*, int iconified) {
}

void GLFWView::onFramebufferSize (GLFWwindow* window, int w, int h) {
  auto thiz = instance();
  thiz->_listener->onResize({w, h});
}

void GLFWView::onMouseButton (GLFWwindow*, int button, int action, int mods) {
  auto code = __buttonMapping[button];
  auto thiz = instance();
  if (action == GLFW_PRESS)
    thiz->_listener->onMousePress(code);
  else
    thiz->_listener->onMouseRelease(code);
}

void GLFWView::onCursorPos (GLFWwindow*, double x, double y) {
  auto thiz = instance();
  thiz->_listener->onMouseMove({float(x), float(y)});
}

void GLFWView::onCursorEnter (GLFWwindow*, int entered) {
  auto thiz = instance();
  if (entered == GL_TRUE)
    thiz->_listener->onMouseEnter();
  else
    thiz->_listener->onMouseLeave();
}

void GLFWView::onScroll (GLFWwindow*, double x, double y) {
  auto thiz = instance();
  thiz->_listener->onMouseScroll({float(x), float(y)});
}

void GLFWView::onKey (GLFWwindow*, int key, int scancode, int action, int mods) {
  auto code = __keyMapping[key];
  if (code == KeyEvent::Unknown)
    return;
  auto thiz = instance();
  switch (action) {
    case GLFW_PRESS: thiz->_listener->onKeyPress(code); break;
    case GLFW_REPEAT: thiz->_listener->onKeyRepeat(code); break;
    case GLFW_RELEASE: thiz->_listener->onKeyRelease(code); break;
    default: break;
  }
}

void GLFWView::onChar (GLFWwindow*, unsigned int codepoint) {
}



KeyEvent::Key GLFWView::__keyMapping[] = {
  KeyEvent::Unknown, // 0
  KeyEvent::Unknown, // 1
  KeyEvent::Unknown, // 2
  KeyEvent::Unknown, // 3
  KeyEvent::Unknown, // 4
  KeyEvent::Unknown, // 5
  KeyEvent::Unknown, // 6
  KeyEvent::Unknown, // 7
  KeyEvent::Unknown, // 8
  KeyEvent::Unknown, // 9
  KeyEvent::Unknown, // 10
  KeyEvent::Unknown, // 11
  KeyEvent::Unknown, // 12
  KeyEvent::Unknown, // 13
  KeyEvent::Unknown, // 14
  KeyEvent::Unknown, // 15
  KeyEvent::Unknown, // 16
  KeyEvent::Unknown, // 17
  KeyEvent::Unknown, // 18
  KeyEvent::Unknown, // 19
  KeyEvent::Unknown, // 20
  KeyEvent::Unknown, // 21
  KeyEvent::Unknown, // 22
  KeyEvent::Unknown, // 23
  KeyEvent::Unknown, // 24
  KeyEvent::Unknown, // 25
  KeyEvent::Unknown, // 26
  KeyEvent::Unknown, // 27
  KeyEvent::Unknown, // 28
  KeyEvent::Unknown, // 29
  KeyEvent::Unknown, // 30
  KeyEvent::Unknown, // 31
  KeyEvent::Space, // 32
  KeyEvent::Unknown, // 33
  KeyEvent::Unknown, // 34
  KeyEvent::Unknown, // 35
  KeyEvent::Unknown, // 36
  KeyEvent::Unknown, // 37
  KeyEvent::Unknown, // 38
  KeyEvent::CloseQuotation, // 39
  KeyEvent::Unknown, // 40
  KeyEvent::Unknown, // 41
  KeyEvent::Unknown, // 42
  KeyEvent::Unknown, // 43
  KeyEvent::Comma, // 44
  KeyEvent::Minus, // 45
  KeyEvent::Period, // 46
  KeyEvent::Slash, // 47
  KeyEvent::_0, // 48
  KeyEvent::_1, // 49
  KeyEvent::_2, // 50
  KeyEvent::_3, // 51
  KeyEvent::_4, // 52
  KeyEvent::_5, // 53
  KeyEvent::_6, // 54
  KeyEvent::_7, // 55
  KeyEvent::_8, // 56
  KeyEvent::_9, // 57
  KeyEvent::Unknown, // 58
  KeyEvent::Semicolon, // 59
  KeyEvent::Unknown, // 60
  KeyEvent::Equal, // 61
  KeyEvent::Unknown, // 62
  KeyEvent::Unknown, // 63
  KeyEvent::Unknown, // 64
  KeyEvent::A, // 65
  KeyEvent::B, // 66
  KeyEvent::C, // 67
  KeyEvent::D, // 68
  KeyEvent::E, // 69
  KeyEvent::F, // 70
  KeyEvent::G, // 71
  KeyEvent::H, // 72
  KeyEvent::I, // 73
  KeyEvent::J, // 74
  KeyEvent::K, // 75
  KeyEvent::L, // 76
  KeyEvent::M, // 77
  KeyEvent::N, // 78
  KeyEvent::O, // 79
  KeyEvent::P, // 80
  KeyEvent::Q, // 81
  KeyEvent::R, // 82
  KeyEvent::S, // 83
  KeyEvent::T, // 84
  KeyEvent::U, // 85
  KeyEvent::V, // 86
  KeyEvent::W, // 87
  KeyEvent::X, // 88
  KeyEvent::Y, // 89
  KeyEvent::Z, // 90
  KeyEvent::BracketLeft, // 91
  KeyEvent::BackSlash, // 92
  KeyEvent::BracketRight, // 93
  KeyEvent::Unknown, // 94
  KeyEvent::Unknown, // 95
  KeyEvent::OpenQuotation, // 96
  KeyEvent::Unknown, // 97
  KeyEvent::Unknown, // 98
  KeyEvent::Unknown, // 99
  KeyEvent::Unknown, // 100
  KeyEvent::Unknown, // 101
  KeyEvent::Unknown, // 102
  KeyEvent::Unknown, // 103
  KeyEvent::Unknown, // 104
  KeyEvent::Unknown, // 105
  KeyEvent::Unknown, // 106
  KeyEvent::Unknown, // 107
  KeyEvent::Unknown, // 108
  KeyEvent::Unknown, // 109
  KeyEvent::Unknown, // 110
  KeyEvent::Unknown, // 111
  KeyEvent::Unknown, // 112
  KeyEvent::Unknown, // 113
  KeyEvent::Unknown, // 114
  KeyEvent::Unknown, // 115
  KeyEvent::Unknown, // 116
  KeyEvent::Unknown, // 117
  KeyEvent::Unknown, // 118
  KeyEvent::Unknown, // 119
  KeyEvent::Unknown, // 120
  KeyEvent::Unknown, // 121
  KeyEvent::Unknown, // 122
  KeyEvent::Unknown, // 123
  KeyEvent::Unknown, // 124
  KeyEvent::Unknown, // 125
  KeyEvent::Unknown, // 126
  KeyEvent::Unknown, // 127
  KeyEvent::Unknown, // 128
  KeyEvent::Unknown, // 129
  KeyEvent::Unknown, // 130
  KeyEvent::Unknown, // 131
  KeyEvent::Unknown, // 132
  KeyEvent::Unknown, // 133
  KeyEvent::Unknown, // 134
  KeyEvent::Unknown, // 135
  KeyEvent::Unknown, // 136
  KeyEvent::Unknown, // 137
  KeyEvent::Unknown, // 138
  KeyEvent::Unknown, // 139
  KeyEvent::Unknown, // 140
  KeyEvent::Unknown, // 141
  KeyEvent::Unknown, // 142
  KeyEvent::Unknown, // 143
  KeyEvent::Unknown, // 144
  KeyEvent::Unknown, // 145
  KeyEvent::Unknown, // 146
  KeyEvent::Unknown, // 147
  KeyEvent::Unknown, // 148
  KeyEvent::Unknown, // 149
  KeyEvent::Unknown, // 150
  KeyEvent::Unknown, // 151
  KeyEvent::Unknown, // 152
  KeyEvent::Unknown, // 153
  KeyEvent::Unknown, // 154
  KeyEvent::Unknown, // 155
  KeyEvent::Unknown, // 156
  KeyEvent::Unknown, // 157
  KeyEvent::Unknown, // 158
  KeyEvent::Unknown, // 159
  KeyEvent::Unknown, // 160
  KeyEvent::Unknown, // 161
  KeyEvent::Unknown, // 162
  KeyEvent::Unknown, // 163
  KeyEvent::Unknown, // 164
  KeyEvent::Unknown, // 165
  KeyEvent::Unknown, // 166
  KeyEvent::Unknown, // 167
  KeyEvent::Unknown, // 168
  KeyEvent::Unknown, // 169
  KeyEvent::Unknown, // 170
  KeyEvent::Unknown, // 171
  KeyEvent::Unknown, // 172
  KeyEvent::Unknown, // 173
  KeyEvent::Unknown, // 174
  KeyEvent::Unknown, // 175
  KeyEvent::Unknown, // 176
  KeyEvent::Unknown, // 177
  KeyEvent::Unknown, // 178
  KeyEvent::Unknown, // 179
  KeyEvent::Unknown, // 180
  KeyEvent::Unknown, // 181
  KeyEvent::Unknown, // 182
  KeyEvent::Unknown, // 183
  KeyEvent::Unknown, // 184
  KeyEvent::Unknown, // 185
  KeyEvent::Unknown, // 186
  KeyEvent::Unknown, // 187
  KeyEvent::Unknown, // 188
  KeyEvent::Unknown, // 189
  KeyEvent::Unknown, // 190
  KeyEvent::Unknown, // 191
  KeyEvent::Unknown, // 192
  KeyEvent::Unknown, // 193
  KeyEvent::Unknown, // 194
  KeyEvent::Unknown, // 195
  KeyEvent::Unknown, // 196
  KeyEvent::Unknown, // 197
  KeyEvent::Unknown, // 198
  KeyEvent::Unknown, // 199
  KeyEvent::Unknown, // 200
  KeyEvent::Unknown, // 201
  KeyEvent::Unknown, // 202
  KeyEvent::Unknown, // 203
  KeyEvent::Unknown, // 204
  KeyEvent::Unknown, // 205
  KeyEvent::Unknown, // 206
  KeyEvent::Unknown, // 207
  KeyEvent::Unknown, // 208
  KeyEvent::Unknown, // 209
  KeyEvent::Unknown, // 210
  KeyEvent::Unknown, // 211
  KeyEvent::Unknown, // 212
  KeyEvent::Unknown, // 213
  KeyEvent::Unknown, // 214
  KeyEvent::Unknown, // 215
  KeyEvent::Unknown, // 216
  KeyEvent::Unknown, // 217
  KeyEvent::Unknown, // 218
  KeyEvent::Unknown, // 219
  KeyEvent::Unknown, // 220
  KeyEvent::Unknown, // 221
  KeyEvent::Unknown, // 222
  KeyEvent::Unknown, // 223
  KeyEvent::Unknown, // 224
  KeyEvent::Unknown, // 225
  KeyEvent::Unknown, // 226
  KeyEvent::Unknown, // 227
  KeyEvent::Unknown, // 228
  KeyEvent::Unknown, // 229
  KeyEvent::Unknown, // 230
  KeyEvent::Unknown, // 231
  KeyEvent::Unknown, // 232
  KeyEvent::Unknown, // 233
  KeyEvent::Unknown, // 234
  KeyEvent::Unknown, // 235
  KeyEvent::Unknown, // 236
  KeyEvent::Unknown, // 237
  KeyEvent::Unknown, // 238
  KeyEvent::Unknown, // 239
  KeyEvent::Unknown, // 240
  KeyEvent::Unknown, // 241
  KeyEvent::Unknown, // 242
  KeyEvent::Unknown, // 243
  KeyEvent::Unknown, // 244
  KeyEvent::Unknown, // 245
  KeyEvent::Unknown, // 246
  KeyEvent::Unknown, // 247
  KeyEvent::Unknown, // 248
  KeyEvent::Unknown, // 249
  KeyEvent::Unknown, // 250
  KeyEvent::Unknown, // 251
  KeyEvent::Unknown, // 252
  KeyEvent::Unknown, // 253
  KeyEvent::Unknown, // 254
  KeyEvent::Unknown, // 255
  KeyEvent::Esc, // 256
  KeyEvent::Enter, // 257
  KeyEvent::Tab, // 258
  KeyEvent::BackSpace, // 259
  KeyEvent::Insert, // 260
  KeyEvent::Delete, // 261
  KeyEvent::Right, // 262
  KeyEvent::Left, // 263
  KeyEvent::Down, // 264
  KeyEvent::Up, // 265
  KeyEvent::PageUp, // 266
  KeyEvent::PageDown, // 267
  KeyEvent::Home, // 268
  KeyEvent::End, // 269
  KeyEvent::Unknown, // 270
  KeyEvent::Unknown, // 271
  KeyEvent::Unknown, // 272
  KeyEvent::Unknown, // 273
  KeyEvent::Unknown, // 274
  KeyEvent::Unknown, // 275
  KeyEvent::Unknown, // 276
  KeyEvent::Unknown, // 277
  KeyEvent::Unknown, // 278
  KeyEvent::Unknown, // 279
  KeyEvent::CapsLock, // 280
  KeyEvent::ScrollLock, // 281
  KeyEvent::NumLock, // 282
  KeyEvent::Print, // 283
  KeyEvent::Pause, // 284
  KeyEvent::Unknown, // 285
  KeyEvent::Unknown, // 286
  KeyEvent::Unknown, // 287
  KeyEvent::Unknown, // 288
  KeyEvent::Unknown, // 289
  KeyEvent::F1, // 290
  KeyEvent::F2, // 291
  KeyEvent::F3, // 292
  KeyEvent::F4, // 293
  KeyEvent::F5, // 294
  KeyEvent::F6, // 295
  KeyEvent::F7, // 296
  KeyEvent::F8, // 297
  KeyEvent::F9, // 298
  KeyEvent::F10, // 299
  KeyEvent::F11, // 300
  KeyEvent::F12, // 301
  KeyEvent::Unknown, // 302
  KeyEvent::Unknown, // 303
  KeyEvent::Unknown, // 304
  KeyEvent::Unknown, // 305
  KeyEvent::Unknown, // 306
  KeyEvent::Unknown, // 307
  KeyEvent::Unknown, // 308
  KeyEvent::Unknown, // 309
  KeyEvent::Unknown, // 310
  KeyEvent::Unknown, // 311
  KeyEvent::Unknown, // 312
  KeyEvent::Unknown, // 313
  KeyEvent::Unknown, // 314
  KeyEvent::Unknown, // 315
  KeyEvent::Unknown, // 316
  KeyEvent::Unknown, // 317
  KeyEvent::Unknown, // 318
  KeyEvent::Unknown, // 319
  KeyEvent::Num0, // 320
  KeyEvent::Num1, // 321
  KeyEvent::Num2, // 322
  KeyEvent::Num3, // 323
  KeyEvent::Num4, // 324
  KeyEvent::Num5, // 325
  KeyEvent::Num6, // 326
  KeyEvent::Num7, // 327
  KeyEvent::Num8, // 328
  KeyEvent::Num9, // 329
  KeyEvent::NumDot, // 330
  KeyEvent::NumDiv, // 331
  KeyEvent::NumMul, // 332
  KeyEvent::NumSub, // 333
  KeyEvent::NumAdd, // 334
  KeyEvent::NumEq, // 335
  KeyEvent::NumEq, // 336
  KeyEvent::Unknown, // 337
  KeyEvent::Unknown, // 338
  KeyEvent::Unknown, // 339
  KeyEvent::Shift, // 340
  KeyEvent::Control, // 341
  KeyEvent::Alt, // 342
  KeyEvent::Super, // 343
  KeyEvent::ShiftRight, // 344
  KeyEvent::ControlRight, // 345
  KeyEvent::AltRight, // 346
  KeyEvent::SuperRight, // 347
  KeyEvent::Menu, // 348
};

MouseEvent::Button GLFWView::__buttonMapping[] = {
  MouseEvent::Left,
  MouseEvent::Right,
  MouseEvent::Middle,
  MouseEvent::Extra_1,
  MouseEvent::Extra_2,
  MouseEvent::Extra_3,
  MouseEvent::Extra_4,
  MouseEvent::Extra_5,
  MouseEvent::Extra_6,
  MouseEvent::Extra_7,
  MouseEvent::Extra_8,
  MouseEvent::Extra_9,
  MouseEvent::Extra_10,
  MouseEvent::Extra_11,
  MouseEvent::Extra_12,
};
